#include <stdlib.h>
#include <string.h>
#include "StoreSymInfo.h"
#include "SymEntry.h"
#include "SymInfo.h"

StoreSymInfo::StoreSymInfo(size_t initLength) :
		length(initLength) {
	store = (SymInfo*) new char[length * sizeof(SymInfo)];

	lastBlock = store;
	lastBlockSize = length;
	*((int**) store) = 0;

	sizeFree = lastBlockSize - sizeof(SymInfo);
	startFreeSpace = (SymInfo*) ((store + sizeof(SymInfo)));
}

StoreSymInfo::~StoreSymInfo() {
	int* next = *(int**) &store[0];
	int* current = (int*) &store[0];

	delete[] (char*) current;
	current = next;
	while (current != 0) {
		next = *(int**) current;
		delete[] (char*) current;
		current = next;
	}
}

void StoreSymInfo::expand() {
	lastBlockSize *= 2;
	SymInfo* newBlock = (SymInfo*) new char[lastBlockSize * sizeof(SymInfo)];

	writeNextBlockPosition(newBlock); // write pointer to new block

	lastBlock = newBlock;
	// skip over the pointer we just wrote
	startFreeSpace = newBlock + sizeof(SymInfo*);
	*((SymInfo**) lastBlock) = 0;
	sizeFree = lastBlockSize - sizeof(SymInfo*);
}

void StoreSymInfo::writeNextBlockPosition(SymInfo* next) {
	*((SymInfo**) lastBlock) = next;
}

SymInfo* StoreSymInfo::add(char* lexem, TokenType type) {
	SymInfo* oldStartFreeSpace = startFreeSpace;
	startFreeSpace->Set(lexem, type);

	// make sure that we always have space for adding stuff
	--sizeFree;
	if (sizeFree == 0) {
		expand();
	} else {
		++startFreeSpace;
	}
	return oldStartFreeSpace;
}
